<template>
  <div class="comment__warpper">
    <el-image class="comment__avatar" :src="formattedComment.avatar">
      <template #error>
        <el-image :src="avatarFallback" />
      </template>
    </el-image>
    <div class="comment__info">
      <a
        class="comment__user"
        target="_blank"
        :href="formattedComment.site_url"
        v-if="formattedComment.site_url"
        >{{ formattedComment.nick_name }}</a
      >
      <span class="comment__user" v-else>{{ formattedComment.nick_name }}</span>
      <span class="comment__time">{{ formattedComment.create_time }}</span>
      <div class="comment__content">{{ formattedComment.content }}</div>

      <!-- 组件的做法,小麻烦,直接封装吧 -->
      <!-- <a-button class="btn-reply" size="small">
        <template #icon> <icon-svg icon="reply" :size="14" /></template>
        回复</a-button
      > -->
      <!-- 自己使用具名插槽封装的组件 -->
      <my-button
        class="btn-reply"
        size="small"
        icon="reply"
        @click="showReplyFrom"
        >回复</my-button
      >

      <!-- 回复空间 -->
      <div class="reply-form" v-if="isShowReply && isActive">
        <a-input
          ref="replyInputRef"
          v-model:value="replyInputContent"
          size="small"
          :placeholder="replyPlaceholder"
        />
        <a-button
          size="small"
          class="btn-confirm-reply"
          :loading="isReplyLoading"
          v-throttle="{ func: AsyncReply, wait: 1500, type: 'click' }"
          >发布</a-button
        >
      </div>

      <div class="reply__list" v-if="formattedComment.replies.length > 0">
        <div
          class="reply__card"
          v-for="reply in formattedComment.replies"
          :key="reply.id"
        >
          <div class="reply__header">
            <el-image class="reply__avatar" :src="reply.avatar" lazy>
              <template #error>
                <el-image :src="replyAvatarFallback" />
              </template>
            </el-image>

            <div class="reply__subinfo">
              <span class="reply__info"
                >{{ reply.nick_name }}回复{{
                  reply.reply_name || formattedComment.nick_name
                }}</span
              >
              <span class="reply__time">{{ reply.create_time }}</span>
            </div>
          </div>

          <div class="reply__content">
            {{ reply.content }}
          </div>
          <my-button
            class="btn-reply"
            size="small"
            icon="reply"
            @click="showReplySub(reply)"
            >回复</my-button
          >

          <!-- 由于二级回复可能会有很多,有没有可能会有回复的回复,这是值得深思的事情,因此需要考虑一下 -->
          <div
            class="reply-form"
            v-if="isSubShowReply && isActive && replySubid === reply.id"
          >
            <a-input
              v-focus
              v-model:value="subReplyForm.content"
              size="small"
              :placeholder="replySubPlaceholder"
            />
            <a-button
              :loading="isReplySubLoading"
              size="small"
              class="btn-confirm-reply"
              v-throttle="{ func: AsyncSubReply, wait: 1500, type: 'click' }"
              >发布</a-button
            >
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script lang="ts">
import { Input, message, Modal } from 'ant-design-vue';
import {
  computed,
  defineComponent,
  nextTick,
  PropType,
  reactive,
  ref,
} from 'vue';
import { useStore } from '@/store';
import { CommentDTO, CommentUserInfo } from '@/bean/dto';
import { format } from '@/utils/date-utils';
import DOMPurify from 'dompurify';
import { replyService } from '@/api/reply';
import { useAsyncLoading } from '@/hooks';

export default defineComponent({
  components: {
    [Input.name]: Input,
  },
  props: {
    comment: {
      type: Object as PropType<CommentDTO>,
      required: true,
    },
    isActive: {
      type: Boolean,
    },
  },
  emits: ['UserInfoisEmpty', 'setActive'],
  setup(props, { emit }) {
    // vuex
    const store = useStore();
    const commentsUserInfo = computed(() => store.state.commentUserInfo);

    const comment = props.comment;

    const avatarFallback = require('@/assets/img/comment-avatar.svg');
    const replyAvatarFallback = require('@/assets/img/reply-avatar.svg');

    // 展现评论区数据(格式化评论)
    const formattedComment = computed(() => {
      return {
        ...comment,
        avatar: comment.avatar || avatarFallback,
        create_time: format(comment.create_time),
        replies: comment.replies.map((reply) => {
          return {
            ...reply,

            avatar: reply.avatar || replyAvatarFallback,
            create_time: format(reply.create_time),
          };
        }),
      };
    });
    // 一级回复
    const isShowReply = ref(false);
    // 子级回复
    const isSubShowReply = ref(false);
    const replyInputRef = ref<HTMLInputElement>();
    const replyInputContent = ref('');
    const replyPlaceholder = ref('');
    // 二级回复功能

    const replySubid = ref(-1);
    const replySubPlaceholder = ref();
    // 一级回复
    const showReplyFrom = () => {
      //首先判断下游客用户信息是否存在
      if (!commentsUserInfo.value) {
        emit('UserInfoisEmpty');
      } else {
        emit('setActive', comment.id);
        isShowReply.value = true;
        isSubShowReply.value = false;
        replyPlaceholder.value = `@ ${comment.nick_name}`;
        nextTick(() => {
          console.log(replyInputRef.value);

          replyInputRef.value?.focus();
        });
      }
    };

    // 回复评论功能
    const handleReply = async () => {
      if (!replyInputContent.value) {
        message.warn('请输入有效评论');
      }

      // 防止xxs注入攻击
      const xxsContent = DOMPurify.sanitize(replyInputContent.value);
      if (!xxsContent) {
        message.warn('哥,别用xxs注入攻击了,我只是一个小菜鸟');
        return;
      }
      await replyService.add({
        ...(commentsUserInfo.value as CommentUserInfo),
        // 回复内容
        content: xxsContent,
        // 记录网页的url，用于发邮件时附上链接
        jump_url: window.location.href,
        // 回复的评论id
        comment_id: comment.id,
        // 父级回复的id，这里是一级回复表单，所以为null即可
        parent_id: null,
        // 文章id
        article_id: comment.article_id,
        // 默认是待审核状态
        approved: 1,
      });

      Modal.success({
        title: '温馨提示',
        content: '您的回复已经提交成功，待审核后即可生效！',
      });
      isShowReply.value = false;
      replyInputContent.value = '';
    };

    const { trigger: AsyncReply, loading: isReplyLoading } =
      useAsyncLoading(handleReply);

    // 显示二级回复
    const subReplyForm = reactive({
      content: '',
      parent_id: -1,
    });

    // 显示子回复的输入框
    const showReplySub = (reply: any) => {
      if (!commentsUserInfo.value) {
        emit('UserInfoisEmpty');
      } else {
        emit('setActive', comment.id);
        replySubid.value = reply.id;
        replySubPlaceholder.value = `@ ${reply.nick_name}`;
        isShowReply.value = false;
        isSubShowReply.value = true;

        // 重置输入框内容
        subReplyForm.content = '';
        // 这里给二级回复表单的parent_id赋值
        subReplyForm.parent_id = reply.id;
      }
    };

    // 二级回复功能
    const handleSubReply = async () => {
      if (!subReplyForm.content) {
        message.warn('您还没输入内容');
      }

      // 防止xxs注入攻击
      const xxsContent = DOMPurify.sanitize(subReplyForm.content);
      if (!xxsContent) {
        message.warn('哥,别用xxs注入攻击了,我只是一个小菜鸟');
        return;
      }
      await replyService.add({
        ...(commentsUserInfo.value as CommentUserInfo),
        // 回复内容
        content: xxsContent,
        // 记录网页的url，用于发邮件时附上链接
        jump_url: window.location.href,
        // 回复的评论id
        comment_id: comment.id,
        // 父级回复的id
        parent_id: subReplyForm.parent_id,
        // 文章id
        article_id: comment.article_id,
        // 默认是待审核状态
        approved: 1,
      });

      Modal.success({
        title: '温馨提示',
        content: '您的回复已经提交成功，待审核后即可生效！',
      });
      isShowReply.value = false;
      subReplyForm.content = '';
      subReplyForm.parent_id = -1;

      // 这里踩坑,不能用ref获取dom元素,因为层级太多,所以ref有时灵有时不灵,
      // 当时研究了一波为什么,v-if套的层级太多了,但是你用v-show设计的不太行,万一就没用到这个dom元素呢
      //
      // nextTick(()=>{})
    };

    const { trigger: AsyncSubReply, loading: isReplySubLoading } =
      useAsyncLoading(handleSubReply);

    return {
      avatarFallback,
      replyAvatarFallback,
      showReplyFrom,
      isShowReply,
      showReplySub,
      formattedComment,
      isSubShowReply,
      replyInputRef,
      replyPlaceholder,
      replyInputContent,
      AsyncReply,
      isReplyLoading,
      replySubid,
      subReplyForm,
      AsyncSubReply,
      isReplySubLoading,
      replySubPlaceholder,
    };
  },
});
</script>

<style scoped lang="scss">
.comment__warpper {
  display: flex;
  padding: 8px 12px;
  background-color: #fff;
  border-radius: 4px;
  box-shadow: 0 2px 26px rgb(7 17 27 / 12%);
}

.comment__avatar {
  width: 40px;
  height: 40px;
}

.comment__info {
  flex: 1;
  margin-left: 6px;
}
.comment__user {
  color: #5fb7ac;
  font-size: 16px;
}

.comment__time {
  display: block;
  font-size: 12px;
  color: #999;
}
.comment__content {
  color: #333;
  font-size: 16px;
  padding-bottom: 4px;
}
.btn-reply {
  font-size: 12px;
}
.reply-form {
  margin-top: 10px;
  display: flex;
  align-items: center;
}
.btn-confirm-reply {
  margin: 0 0 0 10px;
  font-size: 12px;
  height: 22px;
  padding: 0 4px;
}

.reply__list {
  margin-top: 10px;
  border-top: 1px solid #ccc;
}
.reply__card {
  text-align: left;
  padding: 10px 0;
  border-bottom: 1px solid #eee;
}

.reply__header {
  display: flex;
}
:deep(.reply__avatar) {
  width: 24px;
  height: 24px;
}

.reply__subinfo {
  margin-left: 4px;
  padding-top: 4px;
  display: flex;
  font-size: 12px;
}
.reply__info {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.reply__time {
  margin-left: 4px;
  color: #999;
}

.reply__content {
  margin-bottom: 4px;
  color: #333;
  font-size: 16px;
}
</style>
